import {
	notNull,
	hasProperty,
	isType,
	isPromise,
	defer,
	getType,
} from '../helpers/utils';
import { validatorMethods as _methods } from './methods';
import {
	IValidateResult,
	IValidateRule,
} from '../interfaces/validataor.interface';

/**
 * 验证方法
 * @param data 验证的数据
 * @param rules 验证字段的一则
 */
async function validate(
	data: any,
	rules: IValidateRule[],
	name: string,
): Promise<IValidateResult> {
	const checkResult: IValidateResult = {
		name: name,
		result: true,
		type: null,
		rule: null,
		validatorErrorMessage: '',
	};
	const { resolve, promise } = defer(); // 创建一个promise
	for (let i = 0; i < rules.length; i++) {
		checkResult.rule = rules[i]; // 记录当前规则
		const { required, pattern, params, validator } = rules[
			i
		] as IValidateRule;
		const type = (
			getType(pattern) === 'string' ? pattern : 'regExp'
		) as string;

		// 检查required配置
		if (required && !notNull(data)) {
			checkResult.result = false;
			checkResult.type = 'required';
			resolve(checkResult);
			break;
		}

		// 检验类型
		if (pattern) {
			// 如果是非必填，同时值为空的时候，忽略类型验证
			if (!['', undefined].includes(data)) {
				// 如果为自定义正则
				// @ts-ignore
				if (type === 'regExp') {
					// @ts-ignore
					if (!pattern.test(data)) {
						checkResult.result = false;
						checkResult.type = 'regExp';
						resolve(checkResult);
						break;
					}
				} else {
					// 检查是否定义type类型
					if (!hasProperty(_methods, type)) {
						checkResult.result = false;
						checkResult.type = 'type';
						resolve(checkResult);
						console.error(`rule type=${type} is not defined！`);
						break;
					}
					const typeCheck = _methods[type](data, params);
					if (!typeCheck) {
						checkResult.result = false;
						checkResult.type = 'type';
						resolve(checkResult);
						break;
					}
				}
			}
		}

		// 检查validator自定义验证
		if (validator) {
			const { result, message } = await _customValidate(
				rules[i],
				data,
				name,
			);
			if (!result) {
				checkResult.result = false;
				checkResult.type = 'validator';
				checkResult.validatorErrorMessage = message as string;
				resolve(checkResult);
				break;
			}
		}

		// 都已近走过了则说明成功
		resolve(checkResult);
	}
	return promise;
}

/**
 * 自定义验证规则
 * @param rule
 * @param value
 * @param field
 * @returns
 */
async function _customValidate(
	rule: IValidateRule,
	value: any,
	field: string,
): Promise<{
	result: boolean;
	message: string | null;
}> {
	const { resolve, promise } = defer(); // 创建promise
	const _result = (state: boolean, message: string | null) => {
		resolve({ result: state, message: message });
	};
	try {
		const { validator } = rule;
		// 是否为函数自定义验证
		if (validator && isType(validator, 'function')) {
			validator(value, rule, (error?: Error) => {
				if (error && error instanceof Error) {
					_result(false, error.message);
					return;
				}
				_result(true, null);
			});
		} else {
			const message = `There is a validator in field ${field} that is not of type function`;
			console.warn(message);
			_result(false, message);
		}
	} catch (error: any) {
		_result(false, error);
	}
	return promise;
}

export { validate };
